{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Pytorch神经网络构建(二)（13-28节）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. 神经网络与深度学习"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.1 Fashion-MNIST 数据集的起源"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 计算机程序一般由两个主要部分组成：代码和数据\n",
    "* 对于深度学习而言，软件即为网络本身，尤其是在训练过程中通过训练产生的权重\n",
    "* 神经网络程序员的工作是通过训练来监督和指导学习过程(可以看做是编写软件或代码的间接方式)\n",
    "#### 3.1.1 Fashion-MNIST数据集\n",
    "* MNIST是非常著名的手写数字数据集 (M:Modify; NIST: National Institute of Standard and Technology)\n",
    "* MNIST中共有7万张图像：6万张用于训练；1万张用于测试；共0—9十个类别\n",
    "* Fashion-MNIST数据集来自Zalando网站：10类别对应10种服饰；7万张 28x28的灰度图像\n",
    "* Fashion-MNIST的目的是取代MNIST数据集，用作基准来测试机器学习算法\n",
    "* Fashion-MNIST与MNIST数据集的异同：(1)异：MNIST数据集中图像都是手写图像，而Fashion-MNIST中的是真实图像；(2)同：这两个数据集具有相同的数据规模，图像大小，数据格式，以及训练集和测试集的分割方式\n",
    "* MNIST为何如此受欢迎：1.该数据集的规模允许深度学习研究者快速地检查和复现它们的算法；2.在所有的深度学习框架中都能使用该数据集\n",
    "* Pytorch中的torchvision包可以加载fashion-mnist数据集"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.2 使用torchvision导入和加载数据集\n",
    "#### 3.2.1 创建深度学习项目的流程：\n",
    "1. 准备数据集\n",
    "2. 创建网络模型\n",
    "3. 训练网络模型\n",
    "4. 分析结果\n",
    "#### 3.2.2 数据准备遵守ETL过程：\n",
    "* 提取(extract)、转换(transform)、加载(load)\n",
    "* pytorch中自带的包，能够将ETL过程变得简单\n",
    "#### 3.2.3 数据的准备：\n",
    "* 1.提取：从源数据中获取fashion-mnist图像数据\n",
    "* 2.转换：将数据转换成张量的形式\n",
    "* 3.加载：将数据封装成对象，使其更容易访问\n",
    "* * Fashion-MNIST 与 MNIST数据集在调用上最大的不同就是URL的不同\n",
    "* * torch.utils.data.Dataset:一个用于表示数据集的抽象类\n",
    "* * torch.utils.data.DataLoader: 包装数据集并提供对底层的访问"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Using downloaded and verified file: ./data/FashionMNIST\\FashionMNIST\\raw\\train-images-idx3-ubyte.gz\n",
      "Extracting ./data/FashionMNIST\\FashionMNIST\\raw\\train-images-idx3-ubyte.gz\n",
      "Using downloaded and verified file: ./data/FashionMNIST\\FashionMNIST\\raw\\train-labels-idx1-ubyte.gz\n",
      "Extracting ./data/FashionMNIST\\FashionMNIST\\raw\\train-labels-idx1-ubyte.gz\n",
      "Using downloaded and verified file: ./data/FashionMNIST\\FashionMNIST\\raw\\t10k-images-idx3-ubyte.gz\n",
      "Extracting ./data/FashionMNIST\\FashionMNIST\\raw\\t10k-images-idx3-ubyte.gz\n",
      "Using downloaded and verified file: ./data/FashionMNIST\\FashionMNIST\\raw\\t10k-labels-idx1-ubyte.gz\n",
      "Extracting ./data/FashionMNIST\\FashionMNIST\\raw\\t10k-labels-idx1-ubyte.gz\n",
      "Processing...\n",
      "Done!\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "import torchvision\n",
    "import torchvision.transforms as transforms # 可帮助对数据进行转换\n",
    "\n",
    "train_set = torchvision.datasets.FashionMNIST(\n",
    "    root = './data/FashionMNIST',   # 数据集在本地的存储位置\n",
    "    train = True,                   # 数据集用于训练\n",
    "    download = True,                # 如果本地没有数据，就自动下载\n",
    "    transform = transforms.Compose([\n",
    "        transforms.ToTensor()         \n",
    "    ])                              # 将图像转换成张量\n",
    ")\n",
    "\n",
    "train_loader = torch.utils.data.DataLoader(train_set)\n",
    "# 训练集被打包或加载到数据加载器中，可以以我们期望的格式来访问基础数据；\n",
    "# 数据加载器使我们能够访问数据并提供查询功能"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.3 数据集的访问"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch \n",
    "import torchvision\n",
    "import torchvision.transforms as transforms\n",
    "\n",
    "train_set = torchvision.datasets.FashionMNIST(\n",
    "    root = './data/FashionMNIST',\n",
    "    train = True,\n",
    "    download = True,\n",
    "    transform = transforms.Compose([\n",
    "        transforms.ToTensor()\n",
    "    ])\n",
    ")\n",
    "\n",
    "train_loader = torch.utils.data.DataLoader(train_set, batch_size=10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "60000\n",
      "tensor([9, 0, 0,  ..., 3, 0, 5])\n",
      "tensor([6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000])\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\wanyu\\Anaconda3\\lib\\site-packages\\torchvision\\datasets\\mnist.py:43: UserWarning: train_labels has been renamed targets\n",
      "  warnings.warn(\"train_labels has been renamed targets\")\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "torch.set_printoptions(linewidth=120)     # 设置打印行宽\n",
    "print(len(train_set))\n",
    "print(train_set.train_labels)\n",
    "print(train_set.train_labels.bincount())    # bincount:张量中每个值出现的频数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 要想从训练集对象中访问一个单独的元素，首先要将一个训练集对象(train_set)传递给python的iter()函数，以此返回一个表示数据流的对象；然后就可以使用next函数来获取数据流中的元素"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n",
      "<class 'tuple'>\n"
     ]
    }
   ],
   "source": [
    "# 查看单个样本\n",
    "sample = next(iter(train_set))\n",
    "print(len(sample))\n",
    "print(type(sample))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.Size([1, 28, 28])"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 将sample解压成图像和标签\n",
    "image = sample[0]\n",
    "label = sample[1]\n",
    "image.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "label: 9\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 显示图像和标签\n",
    "plt.imshow(image.squeeze(), cmap='gray')    # 将[1, 28, 28]->[28,28]\n",
    "print('label:', label)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n",
      "<class 'list'>\n",
      "torch.Size([10, 1, 28, 28])\n",
      "torch.Size([10])\n"
     ]
    }
   ],
   "source": [
    "# 查看批量样本\n",
    "batch= next(iter(train_loader))\n",
    "print(len(batch))\n",
    "print(type(batch))\n",
    "images, labels = batch\n",
    "print(images.shape)\n",
    "print(labels.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.Size([3, 32, 302])\n",
      "labels: tensor([9, 0, 0, 3, 0, 2, 7, 2, 5, 5])\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1080x1080 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 画出一批的图像\n",
    "grid= torchvision.utils.make_grid(images,nrow =10)\n",
    "print(grid.shape)\n",
    "plt.figure(figsize=(15, 15))\n",
    "plt.imshow(np.transpose(grid,(1,2,0)))   # 将张量转换成矩阵\n",
    "print('labels:', labels)\n",
    "# 可以通过改变batchsize来显示更多的数据"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 3.3.1 不平衡数据集\n",
    "关于数据不均衡的问题可以读文章：A systematic study of the class imbalance problem in convolutional neural networks"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.4 网络建立\n",
    "#### 3.4.1 class和object的区分\n",
    "* class 就是一个实际对象的蓝图或描述\n",
    "* object 就是事物本身\n",
    "* 创建的对象需要在类的实例中调用对象\n",
    "* * 一个给定类的所有实例都有两个核心组件：方法和属性\n",
    "* * 方法代表代码，属性代表数据；方法和属性是由类定义的\n",
    "* * 属性用于描述对象的特征；方法用于描述对象的行为，即对象能够做什么\n",
    "* * 在一个项目中可以有许多对象，即给定类的实例可以同时存在（可在一个类中创建多个对象）\n",
    "* * 类用于封装方法和属性"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 3.4.2 类和实例(对象)<python基础知识补充>\n",
    "* 类是抽象的模板，用于表述具有相同属性和方法的对象的集合，类的命名尽量见名知意\n",
    "* 对象是真实的，见得到摸得着的东西\n",
    "* 类的定义：class 类名():\n",
    "* 类的组成：类名；属性（一组数据）；方法（允许进行的操作）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 类的创建\n",
    "class Lizard:\n",
    "    def __init__(self, name):    # 创建对象时自动运行，不用额外调用,无返回值\n",
    "        self.name = name\n",
    "    def set_name(self, name):\n",
    "        self.name = name"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "deep\n",
      "lizard\n"
     ]
    }
   ],
   "source": [
    "# 类的调用\n",
    "lizard = Lizard('deep')\n",
    "print(lizard.name)\n",
    "lizard.set_name('lizard')\n",
    "print(lizard.name)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 3.4.3 面向对象编程与pytorch的结合\n",
    "* 构建一个神经网络的主要组件是层（pytorch神经网络库中包含了帮助构造层的类）\n",
    "* 神经网络中的每一层都有两个主要组成部分：转换和权重（转换代表代码；权重代表数据）\n",
    "* forward方法（前向传输）：张量通过每层的变换向前流动，直到达到输出层\n",
    "* 构建神经网络时必须提供前向方法，前向方法即为实际的变换\n",
    "* 使用pytorch创建神经网络的步骤：\n",
    "* 1.扩展nn.Module基类\n",
    "* 2.定义层(layers)为类属性\n",
    "* 3.实现前向方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [],
   "source": [
    "# CNN网络的建立\n",
    "import torch.nn as nn\n",
    "class Network(nn.Module):   #()中加入nn.Module可以使得Network类继承Module基类中的所有功能\n",
    "    def __init__(self):\n",
    "        super(Network, self).__init__()     # 对继承的父类的属性进行初始化，使用父类的方法来进行初始化\n",
    "        self.conv1 = nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5)\n",
    "        self.conv2 = nn.Conv2d(in_channels=6, out_channels=12, kernel_size=5)\n",
    "        self.fc1 = nn.Linear(in_features=12*4*4, out_features=120)        # 从卷积层传入线性层需要对张量flatten\n",
    "        self.fc2 = nn.Linear(in_features=120, out_features=60)\n",
    "        self.out = nn.Linear(in_features=60, out_features=10)\n",
    "    def forward(self, t):\n",
    "        # implement the forward pass\n",
    "        return t"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Network(\n",
       "  (conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1))\n",
       "  (conv2): Conv2d(6, 12, kernel_size=(5, 5), stride=(1, 1))\n",
       "  (fc1): Linear(in_features=192, out_features=120, bias=True)\n",
       "  (fc2): Linear(in_features=120, out_features=60, bias=True)\n",
       "  (out): Linear(in_features=60, out_features=10, bias=True)\n",
       ")"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "network = Network()     # 创建网络对象network\n",
    "network"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.5 CNN构建及网络参数的使用\n",
    "在上述的Network类中，我们定义了两个卷积层和一个线性层；两个主要的部分封装在其中，即前向函数的定义和权重张量；每个层中权重张量包含了随着我们的网络在训练过程中学习而更新的权重值（这就是在网络类中将层定义为类属性的原因）；在Module类中，pytorch可以跟踪每一层的权重张量，由于我们在创建Network类时扩展了Module类，也就自动继承了该功能。\n",
    "* Parameter和Argument的区别：\n",
    "* * Parameter在函数定义中使用，可将其看作是占位符；(形参)\n",
    "* * Argument是当函数被调用时传递给函数的实际值；（实参）\n",
    "* Parameter的两种类型：\n",
    "* 1.Hyperparameters:其值是手动和任意确定的；要构建神经网络：kernel_size, out_channels, out_features都需要手动选择\n",
    "* 2.Data dependent Hyperparameters:其值是依赖于数据的参数\n",
    "* * 该参数位于网络的开始或末端，即第一个卷积层的输入通道和最后一个卷积层的输出特征图\n",
    "* * 第一个卷积层的输入通道依赖于构成训练集的图像内部的彩色通道的数量（灰度图像是1，彩色图像是3）\n",
    "* * 输出层的输出特征依赖于训练集中类的数量（fashion-MNIST数据集中的类型为10，则输出层的out_features=10）\n",
    "* * 通常情况下，一层的输入是上一层的输出（即：卷积层中所有输入通道和线性层中的输入特征都依赖于上一层的数据）\n",
    "* 当张量从卷积层传入线性层时，张量必须是flatten的"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "|     Parameter     |     Description      |\n",
    "|:----------------------|:-------------------------|\n",
    "|kernel_size| 设置滤波器的大小；滤波器的数量就是输出通道数|\n",
    "|out_channels| 设置滤波器的数量，即为输出通道数|\n",
    "|out_features| 设置输出张量的大小|"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.6 CNN的权重\n",
    "* 可学习参数：是在训练过程中学习的参数，初值是选择的任意值，其值在网络学习的过程中以迭代的方式进行更新\n",
    "* 说网络在学习是指：网络在学习参数的适合的值，适合的值就是能使损失函数最小化的值\n",
    "* 可学习的参数是网络的权重，存在于每一层中\n",
    "* 当我们扩展类的时候，我们会得到它的所有功能，为了得到它，我们可以添加额外的功能，也可覆盖现有的功能\n",
    "* 在python中，所有特殊的面向对象的方法通常都有前双下划线和后双下划线（__init__, __repr__）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Network类没有扩展Module基类\n",
    "import torch.nn as nn\n",
    "class Network():\n",
    "    def __init__(self):\n",
    "        #super(Network, self).__init__()\n",
    "        self.conv1 = nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5)\n",
    "        self.conv2 = nn.Conv2d(in_channels=6, out_channels=12, kernel_size=5)\n",
    "        self.fc1 = nn.Linear(in_features=12*4*4, out_features=120)\n",
    "        self.fc2 = nn.Linear(in_features=120, out_features=60)\n",
    "        self.out = nn.Linear(in_features=60, out_features=10)\n",
    "    def forward(self,t):\n",
    "        # implement the forward pass\n",
    "        return t"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<__main__.Network at 0x22587c614a8>"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "network = Network()\n",
    "network"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 如下所示，在未扩展module时，可使用__repr__函数实现正常输出"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch.nn as nn\n",
    "class Network():\n",
    "    def __init__(self):\n",
    "        #super(Network, self).__init__()\n",
    "        self.conv1 = nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5)\n",
    "        self.conv2 = nn.Conv2d(in_channels=6, out_channels=12, kernel_size=5)\n",
    "        self.fc1 = nn.Linear(in_features=12*4*4, out_features=120)\n",
    "        self.fc2 = nn.Linear(in_features=120, out_features=60)\n",
    "        self.out = nn.Linear(in_features=60, out_features=10)\n",
    "    def forward(self,t):\n",
    "        # implement the forward pass\n",
    "        return t\n",
    "    def __repr__(self):\n",
    "        return \"lizard\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "lizard"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "network = Network()\n",
    "network"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 可使用点符号来访问指定的层"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1))"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "network.conv1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Parameter containing:\n",
       "tensor([[[[ 0.1325, -0.1655,  0.0673, -0.0484,  0.0902],\n",
       "          [ 0.0786,  0.1996,  0.1328,  0.0983, -0.1863],\n",
       "          [ 0.1934,  0.1327,  0.1872, -0.1716, -0.1416],\n",
       "          [ 0.0615,  0.1469, -0.0585, -0.0281, -0.1568],\n",
       "          [ 0.1771, -0.0918,  0.0050, -0.1956, -0.0712]]],\n",
       "\n",
       "\n",
       "        [[[-0.1567,  0.1811,  0.0305, -0.0664,  0.0489],\n",
       "          [ 0.1546,  0.0873,  0.0405,  0.1718,  0.0761],\n",
       "          [-0.0070,  0.1500, -0.0711, -0.0291, -0.1426],\n",
       "          [-0.1603, -0.0678, -0.0596, -0.0591, -0.0640],\n",
       "          [-0.1811,  0.0783,  0.0253, -0.0430, -0.0880]]],\n",
       "\n",
       "\n",
       "        [[[-0.0098, -0.1732, -0.1451,  0.1322, -0.0294],\n",
       "          [-0.0846, -0.1342,  0.1161, -0.0878,  0.0790],\n",
       "          [-0.0406, -0.1548,  0.0628, -0.1769,  0.0636],\n",
       "          [-0.0008, -0.0608,  0.0189,  0.1753, -0.1456],\n",
       "          [-0.0914, -0.0730, -0.0258,  0.0701,  0.1515]]],\n",
       "\n",
       "\n",
       "        [[[ 0.1788, -0.1618, -0.1806, -0.0663, -0.1851],\n",
       "          [-0.0973,  0.1717,  0.0285,  0.0828, -0.1105],\n",
       "          [-0.1014,  0.0474,  0.1491, -0.0819,  0.1760],\n",
       "          [-0.1993,  0.0348,  0.0440, -0.0355, -0.1349],\n",
       "          [-0.1803,  0.1329,  0.1890,  0.0625, -0.0295]]],\n",
       "\n",
       "\n",
       "        [[[ 0.1935, -0.0924, -0.0569, -0.1453,  0.0372],\n",
       "          [ 0.0052,  0.0265, -0.1254,  0.0028,  0.1498],\n",
       "          [-0.1514, -0.0699, -0.1946,  0.0115,  0.0428],\n",
       "          [-0.0723, -0.0161,  0.1664, -0.1927,  0.1840],\n",
       "          [-0.0158, -0.1727, -0.1929, -0.1457,  0.1194]]],\n",
       "\n",
       "\n",
       "        [[[ 0.0776, -0.1308,  0.1688,  0.1946,  0.1381],\n",
       "          [-0.0123, -0.1584, -0.0497,  0.1271,  0.0759],\n",
       "          [ 0.1713,  0.0891,  0.0306, -0.1303,  0.0739],\n",
       "          [-0.0695,  0.0731,  0.0821, -0.1610, -0.1501],\n",
       "          [ 0.0327,  0.0636,  0.1744, -0.1782,  0.1641]]]], requires_grad=True)"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 输出conv1的权重\n",
    "network.conv1.weight"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.Size([6, 1, 5, 5])"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 输出conv1权重的形状\n",
    "network.conv1.weight.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.Size([120, 192])"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 对于全连接层，由于需要flatten的张量输入，故此时的权重张量是个秩为2的高度、宽度轴\n",
    "network.fc1.weight.shape   # height=>out_features; width=>in_features"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 为了追踪网络中的所有权重张量，pytorch有一个叫Parameter的类，该类扩展了Tensor类， 所以每一层的权重张量就是这个参数类的一个实例\n",
    "* 权重矩阵定义了线性函数(线性映射)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([30., 40., 50.])"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 张量的乘法\n",
    "in_features = torch.tensor([1,2,3,4],dtype=torch.float32)\n",
    "weight_matrix = torch.tensor([\n",
    "    [1,2,3,4],\n",
    "    [2,3,4,5],\n",
    "    [3,4,5,6]\n",
    "], dtype=torch.float32)\n",
    "weight_matrix.matmul(in_features)     # matmul: matrix multiply"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [],
   "source": [
    "# CNN网络的建立\n",
    "import torch.nn as nn\n",
    "class Network(nn.Module):   #()中加入nn.Module可以使得Network类继承Module基类中的所有功能\n",
    "    def __init__(self):\n",
    "        super(Network, self).__init__()     # 对继承的父类的属性进行初始化，使用父类的方法来进行初始化\n",
    "        self.conv1 = nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5)\n",
    "        self.conv2 = nn.Conv2d(in_channels=6, out_channels=12, kernel_size=5)\n",
    "        self.fc1 = nn.Linear(in_features=12*4*4, out_features=120)        # 从卷积层传入线性层需要对张量flatten\n",
    "        self.fc2 = nn.Linear(in_features=120, out_features=60)\n",
    "        self.out = nn.Linear(in_features=60, out_features=10)\n",
    "    def forward(self, t):\n",
    "        # implement the forward pass\n",
    "        return t"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Network(\n",
       "  (conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1))\n",
       "  (conv2): Conv2d(6, 12, kernel_size=(5, 5), stride=(1, 1))\n",
       "  (fc1): Linear(in_features=192, out_features=120, bias=True)\n",
       "  (fc2): Linear(in_features=120, out_features=60, bias=True)\n",
       "  (out): Linear(in_features=60, out_features=10, bias=True)\n",
       ")"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "network = Network()\n",
    "network"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.Size([6, 1, 5, 5])\n",
      "torch.Size([6])\n",
      "torch.Size([12, 6, 5, 5])\n",
      "torch.Size([12])\n",
      "torch.Size([120, 192])\n",
      "torch.Size([120])\n",
      "torch.Size([60, 120])\n",
      "torch.Size([60])\n",
      "torch.Size([10, 10])\n",
      "torch.Size([10])\n"
     ]
    }
   ],
   "source": [
    "# 访问所有的参数\n",
    "# 方法1：\n",
    "for param in network.parameters():\n",
    "    print(param.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "conv1.weight \t\t torch.Size([6, 1, 5, 5])\n",
      "conv1.bias \t\t torch.Size([6])\n",
      "conv2.weight \t\t torch.Size([12, 6, 5, 5])\n",
      "conv2.bias \t\t torch.Size([12])\n",
      "fc1.weight \t\t torch.Size([120, 192])\n",
      "fc1.bias \t\t torch.Size([120])\n",
      "fc2.weight \t\t torch.Size([60, 120])\n",
      "fc2.bias \t\t torch.Size([60])\n",
      "out.weight \t\t torch.Size([10, 10])\n",
      "out.bias \t\t torch.Size([10])\n"
     ]
    }
   ],
   "source": [
    "# 方法2： \n",
    "for name, param in network.named_parameters():\n",
    "    print(name,'\\t\\t', param.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.7 pytorch可调用模块\n",
    "#### 3.7.1 Linear的工作原理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([30., 40., 50.])"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 1. 张量的乘法\n",
    "in_features = torch.tensor([1,2,3,4], dtype=torch.float32)\n",
    "weight_matrix = torch.tensor([\n",
    "    [1,2,3,4],\n",
    "    [2,3,4,5],\n",
    "    [3,4,5,6]\n",
    "], dtype = torch.float32)\n",
    "weight_matrix.matmul(in_features)\n",
    "# 可将上述的权重矩阵看作是一个线性映射（函数），其实现过程与pytorch中的线性层一样"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([-1.4051, -1.1374,  1.6383], grad_fn=<AddBackward0>)"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 2. 线性层\n",
    "fc = nn.Linear(in_features=4, out_features=3)\n",
    "# pytorch 线性层通过将数字4和3传递给构造函数，以创建一个3x4的权重矩阵\n",
    "# 查看in_features张量\n",
    "fc(in_features)\n",
    "# 此时的结果与上述不同是因为这里的weight_matrix是由随机值来初始化的"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([30.4911, 39.7467, 49.7023], grad_fn=<AddBackward0>)"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 在parameter类中包装一个权重矩阵，以使得输出结果与1中一样\n",
    "fc = nn.Linear(in_features=4, out_features=3)\n",
    "fc.weight= nn.Parameter(weight_matrix)\n",
    "fc(in_features)\n",
    "# 此时的结果接近1中的结果却不精确，是因为由bias的存在"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([30., 40., 50.], grad_fn=<SqueezeBackward3>)"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 给bias传递一个false值，以得到精确的输出\n",
    "fc = nn.Linear(in_features=4, out_features=3, bias =False)\n",
    "fc.weight = nn.Parameter(weight_matrix)\n",
    "fc(in_features)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 线性转换的数学表示：\n",
    "* y = Ax + b\n",
    "* A: 权重矩阵张量\n",
    "* x: 输入张量\n",
    "* b: 权重张量\n",
    "* y: 输出张量"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 3.7.2 特殊的调用\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.8 CNN前向方法的实现\n",
    "* 前向方法的实现将使用我们在构造函数中定义的所有层\n",
    "* 前向方法实际上是输入张量到预测的输出张量的映射\n",
    "#### 3.8.1 Input Layer\n",
    "* 输入层是由输入数据决定的\n",
    "* 输入层可以看做是恒等变换 f(x)=x\n",
    "* 输入层通常是隐式存在的"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "class Network(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(Network, self).__init__()\n",
    "        self.conv1 = nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5)\n",
    "        self.conv2 = nn.Conv2d(in_channels=6, out_channels=12, kernel_size=5)\n",
    "        self.fc1 = nn.Linear(in_features=12*4*4, out_features=120)\n",
    "        self.fc2 = nn.Linear(in_features=120,out_features=60)\n",
    "        self.out = nn.Linear(in_features=60, out_features=10)\n",
    "    def forward(self,t):\n",
    "        # (1) input layer\n",
    "        t = t\n",
    "        # (2) hidden conv layer1\n",
    "        t = self.conv1(t)\n",
    "        t = F.relu(t)\n",
    "        t = F.max_pool2d(t, kernel_size=2, stride=2)\n",
    "        # (3) hidden conv layer2\n",
    "        t = self.conv2(t)\n",
    "        t = F.relu(t)\n",
    "        t = F.max_pool2d(t, kernel_size=2, stride=2)\n",
    "        # relu 和 max pooling 都没有权重；激活层和池化层的本质都是操作而非层；层与操作的不同之处在于，层有权重，操作没有\n",
    "        #（4）hidden linear layer2\n",
    "        t = t.reshape(-1, 12*4*4)\n",
    "        t = self.fc1(t)\n",
    "        t = F.relu(t)\n",
    "        # (5) hidden linear layer2\n",
    "        t = self.fc2(t)\n",
    "        t = F.relu(t)\n",
    "        # (6) output layer\n",
    "        t = self.out(t)\n",
    "        # t= F.softmax(t, dim=1)  # 这里暂不使用softmax，在训练中使用交叉熵损失可隐式的表示softmax\n",
    "        # 在隐藏层中，通常使用relu作为非线性激活函数\n",
    "        # 在输出层，有类别要预测时，使用\n",
    "        "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.9 单张图像的预测\n",
    "#### 3.9.1 前向传播(forward propagation)\n",
    "* 是将输入张量转换为输出张量的过程（即：神经网络是将输入张量映射到输出张量的函数）\n",
    "* 前向传播只是将输入张量传递给网络并从网络接收输出的过程的一个特殊名称\n",
    "#### 3.9.2 反向传播(back propagation)\n",
    "* 反向传播通常在前向传播后发生\n",
    "* 使用torch.set_grad_enabled(False)来关闭pytorch的梯度计算，这将阻止pytorch在我们的张量通过网络时构建一个计算图\n",
    "* 计算图通过跟踪张量在网络中传播的每一个计算，来跟踪网络的映射；然后在训练过程中使用这个图来计算导数，也就是损失函数的梯度；关闭并非强制的，但可以减少内存。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.Size([1, 28, 28])\n",
      "torch.Size([1, 1, 28, 28])\n",
      "torch.Size([1, 10])\n",
      "tensor([2])\n",
      "9\n"
     ]
    }
   ],
   "source": [
    "# 单张图像预测\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "import torchvision\n",
    "import torchvision.transforms as transforms\n",
    "\n",
    "# 设置打印格式\n",
    "torch.set_printoptions(linewidth=120)\n",
    "\n",
    "# 一、数据准备\n",
    "train_set = torchvision.datasets.FashionMNIST(\n",
    "    root = './data/FashionMNIST'\n",
    "    ,train = True\n",
    "    ,download = True\n",
    "    , transform = transforms.Compose([\n",
    "        transforms.ToTensor()\n",
    "    ])\n",
    ")\n",
    "# 二、创建网络\n",
    "class Network(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(Network, self).__init__()\n",
    "        self.conv1 = nn.Conv2d(in_channels = 1, out_channels=6, kernel_size=5)\n",
    "        self.conv2 = nn.Conv2d(in_channels = 6, out_channels=12, kernel_size=5)\n",
    "        self.fc1 = nn.Linear(in_features = 12*4*4, out_features=120)\n",
    "        self.fc2 = nn.Linear(in_features = 120, out_features = 60)\n",
    "        self.out = nn.Linear(in_features = 60, out_features=10)\n",
    "    def forward(self, t):\n",
    "        # （1）Input Layer\n",
    "        t = t\n",
    "        # (2) hidden conv1\n",
    "        t = self.conv1(t)\n",
    "        t = F.relu(t)\n",
    "        t = F.max_pool2d(t, kernel_size=2, stride=2)\n",
    "        # (3) hidden conv2 \n",
    "        t = self.conv2(t)\n",
    "        t = F.relu(t)\n",
    "        t = F.max_pool2d(t, kernel_size=2, stride=2)\n",
    "        # (4) hidden linear1\n",
    "        t = t.reshape(-1, 12*4*4)\n",
    "        t = self.fc1(t)\n",
    "        t = F.relu(t)\n",
    "        # (5) hidden linear2\n",
    "        t = self.fc2(t)\n",
    "        t = F.relu(t)\n",
    "        # (6) output\n",
    "        t = self.out(t)\n",
    "        return t\n",
    "        \n",
    "# 调用network实例\n",
    "torch.set_grad_enabled(False)    #关闭pytorch的梯度计算\n",
    "network = Network()\n",
    "sample = next(iter(train_set))\n",
    "image, label = sample\n",
    "print(image.shape)\n",
    "# 显示图像和标签\n",
    "#plt.imshow(image.squeeze(), cmap='gray')    # 将[1, 28, 28]->[28,28]\n",
    "#print('label:', label)\n",
    "# 如上我们得到的图像的形状为[1,28,28];而网络期望的张量是【batchsize,channels, height, width】\n",
    "# 需要使用unsqueeze方法来为其增加一个维度\n",
    "print(image.unsqueeze(0).shape)\n",
    "# 对单张图像进行预测\n",
    "pred = network(image.unsqueeze(0))\n",
    "print(pred.shape)\n",
    "print(pred.argmax(dim=1))\n",
    "print(label)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[0.1045, 0.0886, 0.1129, 0.0915, 0.1119, 0.0959, 0.0992, 0.0995, 0.0920, 0.1040]])\n",
      "tensor(1.)\n"
     ]
    }
   ],
   "source": [
    "# 要想将预测值用概率表示，可以使用softmax\n",
    "print(F.softmax(pred, dim=1))\n",
    "print(F.softmax(pred, dim=1).sum())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.10 单批次图像预测"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.0.1\n",
      "0.2.2\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "import torch.nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "import torchvision\n",
    "import torchvision.transforms as transforms\n",
    "\n",
    "torch.set_printoptions(linewidth=120)\n",
    "\n",
    "print(torch.__version__)\n",
    "print(torchvision.__version__)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 数据准备\n",
    "train_set = torchvision.datasets.FashionMNIST(\n",
    "    root = './data/FashionMNIST'\n",
    "    ,train = True\n",
    "    ,download = True\n",
    "    ,transform = transforms.Compose([\n",
    "        transforms.ToTensor()\n",
    "    ]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 网络创建\n",
    "class Network(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(Network, self).__init__()\n",
    "        self.conv1 = nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5)\n",
    "        self.conv2 = nn.Conv2d(in_channels=6, out_channels=12, kernel_size=5)\n",
    "        self.fc1 = nn.Linear(in_features=12*4*4, out_features=120)\n",
    "        self.fc2 = nn.Linear(in_features=120, out_features=60)\n",
    "        self.out = nn.Linear(in_features=60, out_features=10)\n",
    "    def forward(self, t):\n",
    "        #super(Network, self).__init__()\n",
    "        #(1)Input Layer\n",
    "        t = t\n",
    "        #(2)Conv1\n",
    "        t = F.relu(self.conv1(t))\n",
    "        t = F.max_pool2d(t, kernel_size=2, stride=2)\n",
    "        #(3)Conv2\n",
    "        t = F.relu(self.conv2(t))\n",
    "        t = F.max_pool2d(t, kernel_size=2, stride=2)\n",
    "        #(4)FC1\n",
    "        t = t.reshape(-1,12*4*4)\n",
    "        t = F.relu(self.fc1(t))\n",
    "        #(5)FC2\n",
    "        t = F.relu(self.fc2(t))\n",
    "        #(6)output\n",
    "        t = self.out(t)\n",
    "        return t"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.Size([10, 1, 28, 28])\n",
      "torch.Size([10])\n"
     ]
    }
   ],
   "source": [
    "# 调用network实例\n",
    "torch.set_grad_enabled(False)\n",
    "network = Network()\n",
    "# 从dataloader中取出一批数据\n",
    "data_loader  = torch.utils.data.DataLoader(train_set, batch_size=10)\n",
    "batch = next(iter(data_loader))\n",
    "images, labels = batch\n",
    "print(images.shape)\n",
    "print(labels.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.Size([10, 10])\n",
      "tensor([[ 0.0645,  0.0812, -0.0150,  0.0331, -0.0704, -0.0680,  0.0949,  0.0802,  0.0327,  0.1614],\n",
      "        [ 0.0685,  0.0853, -0.0164,  0.0268, -0.0463, -0.0704,  0.0874,  0.0816,  0.0253,  0.1601],\n",
      "        [ 0.0725,  0.0700, -0.0131,  0.0288, -0.0563, -0.0683,  0.0893,  0.0848,  0.0203,  0.1633],\n",
      "        [ 0.0721,  0.0754, -0.0145,  0.0261, -0.0552, -0.0717,  0.0916,  0.0823,  0.0191,  0.1615],\n",
      "        [ 0.0676,  0.0831, -0.0174,  0.0284, -0.0597, -0.0724,  0.0944,  0.0819,  0.0301,  0.1605],\n",
      "        [ 0.0714,  0.0902, -0.0201,  0.0256, -0.0540, -0.0645,  0.0900,  0.0787,  0.0257,  0.1641],\n",
      "        [ 0.0669,  0.0794, -0.0043,  0.0248, -0.0489, -0.0709,  0.0883,  0.0776,  0.0152,  0.1711],\n",
      "        [ 0.0650,  0.0939, -0.0225,  0.0250, -0.0637, -0.0651,  0.0908,  0.0743,  0.0345,  0.1644],\n",
      "        [ 0.0685,  0.0632, -0.0190,  0.0329, -0.0587, -0.0711,  0.0873,  0.0803,  0.0201,  0.1635],\n",
      "        [ 0.0668,  0.0674, -0.0188,  0.0365, -0.0708, -0.0645,  0.0866,  0.0767,  0.0315,  0.1601]])\n",
      "9\n"
     ]
    }
   ],
   "source": [
    "pred = network(images)\n",
    "print(pred.shape)\n",
    "print(pred)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([9, 9, 9, 9, 9, 9, 9, 9, 9, 9])\n",
      "tensor([9, 0, 0, 3, 0, 2, 7, 2, 5, 5])\n"
     ]
    }
   ],
   "source": [
    "print(pred.argmax(dim=1))\n",
    "print(labels)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[0.1023, 0.1040, 0.0945, 0.0991, 0.0894, 0.0896, 0.1054, 0.1039, 0.0991, 0.1127],\n",
      "        [0.1026, 0.1044, 0.0943, 0.0985, 0.0915, 0.0893, 0.1046, 0.1040, 0.0983, 0.1125],\n",
      "        [0.1032, 0.1029, 0.0947, 0.0987, 0.0907, 0.0896, 0.1049, 0.1044, 0.0979, 0.1130],\n",
      "        [0.1032, 0.1035, 0.0946, 0.0985, 0.0908, 0.0893, 0.1052, 0.1042, 0.0978, 0.1128],\n",
      "        [0.1026, 0.1042, 0.0942, 0.0986, 0.0903, 0.0892, 0.1054, 0.1041, 0.0988, 0.1126],\n",
      "        [0.1029, 0.1048, 0.0939, 0.0983, 0.0907, 0.0898, 0.1048, 0.1036, 0.0983, 0.1129],\n",
      "        [0.1025, 0.1038, 0.0955, 0.0983, 0.0913, 0.0893, 0.1047, 0.1036, 0.0973, 0.1138],\n",
      "        [0.1023, 0.1053, 0.0937, 0.0983, 0.0900, 0.0898, 0.1050, 0.1033, 0.0992, 0.1130],\n",
      "        [0.1030, 0.1024, 0.0944, 0.0994, 0.0907, 0.0896, 0.1049, 0.1042, 0.0981, 0.1133],\n",
      "        [0.1028, 0.1028, 0.0943, 0.0997, 0.0896, 0.0901, 0.1048, 0.1038, 0.0992, 0.1128]])\n",
      "tensor(10.)\n"
     ]
    }
   ],
   "source": [
    "print(F.softmax(pred, dim=1))\n",
    "print(F.softmax(pred,dim=1).sum())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.11 输入张量在通过CNN的过程中的变化\n",
    "#### 3.11.1 CNN 输出特征图尺寸(正方形)\n",
    "* 假设输入特征的大小为n x n\n",
    "* 假设滤波器的大小为 f x f\n",
    "* 令padding为p，步长stride为s\n",
    "* 则输出特征图的大小为 O = ( n - f + 2p )/s + 1\n",
    "#### 3.11.2 CNN 输出特征图尺寸(非正方形)\n",
    "* 假设输入特征的大小为 nh x nw\n",
    "* 假设滤波器的大小为 fh x fw\n",
    "* 令padding为p，步长stride为s\n",
    "* 则输出特征图的高度为 Oh = (nh - fh + 2p)/s + 1\n",
    "* 输出特征图的宽度为 Ow = (nw - fw + 2p)/s + 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.12 训练神经网络的步骤\n",
    "#### 3.12.1 训练神经网络的七个步骤\n",
    "* 从训练集中获取批量数据\n",
    "* 将批量数据传入网络\n",
    "* 计算损失(预测值与真实值之间的差)【需要loss function实现】\n",
    "* 计算损失函数的梯度  【需要back propagation实现】\n",
    "* 通过上一步计算的梯度来更新权重，进而减少损失【需要optimization algorithm实现】\n",
    "* 重复1-5步直到一个epoch执行完成\n",
    "* 重复1-6步直到所设定的epochs执行完成并得到满意的accuracy\n",
    "#### 3.12.2 单批次图像训练"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.0.1\n",
      "0.2.2\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "import torch.optim as optim\n",
    "\n",
    "import torchvision\n",
    "import torchvision.transforms as transforms\n",
    "\n",
    "torch.set_printoptions(linewidth=120)\n",
    "torch.set_grad_enabled(True)  # 这里并不是必须的，默认情况下是打开的\n",
    "\n",
    "print(torch.__version__)\n",
    "print(torchvision.__version__)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 一、训练数据获取\n",
    "train_set = torchvision.datasets.FashionMNIST(\n",
    "    root = './data/FashionMNIST',\n",
    "    train = True,\n",
    "    download = True,\n",
    "    transform = transforms.Compose([\n",
    "        transforms.ToTensor()\n",
    "    ])\n",
    "    )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 104,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 二、创建网络\n",
    "class Network(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(Network, self).__init__()\n",
    "        self.conv1 = nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5)\n",
    "        self.conv2 = nn.Conv2d(in_channels=6, out_channels=12, kernel_size=5)\n",
    "        self.fc1 = nn.Linear(in_features=12*4*4, out_features=120)\n",
    "        self.fc2 = nn.Linear(in_features=120, out_features=60)\n",
    "        self.out = nn.Linear(in_features=60, out_features=10)\n",
    "    \n",
    "    def forward(self, t):\n",
    "        # Input Layer\n",
    "        t = t\n",
    "        # Conv1\n",
    "        t = F.relu(self.conv1(t))\n",
    "        t = F.max_pool2d(t, kernel_size=2, stride=2)\n",
    "        # Conv2\n",
    "        t = F.relu(self.conv2(t))\n",
    "        t = F.max_pool2d(t, kernel_size=2, stride=2)\n",
    "        # FC1\n",
    "        t = t.reshape(-1, 12*4*4)\n",
    "        t = F.relu(self.fc1(t))\n",
    "        # FC2\n",
    "        t = F.relu(self.fc2(t))\n",
    "        # Output\n",
    "        t = self.out(t)\n",
    "        return t"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 105,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2.3116116523742676"
      ]
     },
     "execution_count": 105,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 调用network实例\n",
    "network = Network()\n",
    "train_loader = torch.utils.data.DataLoader(train_set, batch_size=100)\n",
    "batch = next(iter(train_loader))\n",
    "images, labels = batch\n",
    "# 计算损失\n",
    "preds = network(images)\n",
    "loss = F.cross_entropy(preds,labels)\n",
    "loss.item()   #获得损失的值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 106,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 计算损失的梯度\n",
    "loss.backward()      #反向传播"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 107,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2.3116116523742676"
      ]
     },
     "execution_count": 107,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 更新权重\n",
    "optimizer = optim.Adam(network.parameters(), lr =0.01)\n",
    "loss.item()      # 显示当前loss值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 108,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "8\n"
     ]
    }
   ],
   "source": [
    "# 定义函数用于计算预测正确的数目\n",
    "def get_num_correct(preds, labels):\n",
    "    return preds.argmax(dim=1).eq(labels).sum().item()\n",
    "print(get_num_correct(preds, labels))\n",
    "# 更新权重\n",
    "optimizer.step()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 109,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2.2851247787475586\n",
      "8\n"
     ]
    }
   ],
   "source": [
    "preds = network(images)\n",
    "loss = F.cross_entropy(preds,labels)\n",
    "print(loss.item())\n",
    "print(get_num_correct(preds, labels))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 3.12.3 单批次网络训练步骤总结\n",
    "* 从训练集中获取批量数据（lr为学习率:即朝着loss最小的方向走多远）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "network = Network()\n",
    "train_loader = torch.utils.data.DataLoader(train_set, batch_size=100)\n",
    "optimizer = optim.Adam(network.parameters(), lr = 0.01)\n",
    "batch = next(iter(train_loader))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 将批量数据传入network"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "preds = network(images)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 计算loss"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "loss = F.cross_entropy(preds, labels)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 计算loss的梯度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "loss.backward()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 使用计算出的梯度来更新权重，从而减少loss"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "optimizer.step()\n",
    "print('loss1:',loss.item())  #更新前的loss\n",
    "preds = network(images)\n",
    "loss = F.cross_entropy(preds, labels)\n",
    "print('loss2:',loss.item())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.13 单周期(epoch)CNN的训练"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.0.1\n",
      "0.2.2\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "import torch.optim as optim\n",
    "\n",
    "import torchvision\n",
    "import torchvision.transforms as transforms\n",
    "\n",
    "torch.set_printoptions(linewidth=120)\n",
    "torch.set_grad_enabled(True)\n",
    "\n",
    "print(torch.__version__)\n",
    "print(torchvision.__version__)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 数据准备\n",
    "train_set = torchvision.datasets.FashionMNIST(\n",
    "    root = './data/FashionMNIST',\n",
    "    train = True,\n",
    "    download = True,\n",
    "    transform = transforms.Compose([transforms.ToTensor()\n",
    "                                   ]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建网络\n",
    "class Network(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(Network,self).__init__()\n",
    "        self.conv1 = nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5)\n",
    "        self.conv2 = nn.Conv2d(in_channels=6, out_channels=12, kernel_size=5)\n",
    "        self.fc1 = nn.Linear(in_features= 12*4*4, out_features=120)\n",
    "        self.fc2 = nn.Linear(in_features= 120, out_features=60)\n",
    "        self.out = nn.Linear(in_features=60, out_features=10)\n",
    "    \n",
    "    def forward(self, t):\n",
    "        t = t\n",
    "        t = F.relu(self.conv1(t))\n",
    "        t = F.max_pool2d(t, kernel_size =2, stride=2)\n",
    "        t = F.relu(self.conv2(t))\n",
    "        t = F.max_pool2d(t, kernel_size=2, stride=2)\n",
    "        t = t.reshape(-1, 12*4*4)\n",
    "        t = F.relu(self.fc1(t))\n",
    "        t = F.relu(self.fc2(t))\n",
    "        t = self.out(t)\n",
    "        return t\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_num_correct(preds, labels):\n",
    "    return preds.argmax(dim=1).eq(labels).sum().item()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch: 1 loss: 226.4844758361578 total_correct: 51654\n"
     ]
    }
   ],
   "source": [
    "# 创建网络实例\n",
    "network = Network()\n",
    "train_loader = torch.utils.data.DataLoader(train_set, batch_size=100)\n",
    "optimizer = optim.Adam(network.parameters(), lr=0.01)\n",
    "for epoch in range(2):\n",
    "    total_loss = 0\n",
    "    total_correct = 0\n",
    "    for batch in train_loader:   # Get batch\n",
    "        images, labels =batch\n",
    "        preds = network(images)\n",
    "        loss = F.cross_entropy(preds, labels)\n",
    "        optimizer.zero_grad()  #告诉优化器把梯度属性中权重的梯度归零，否则pytorch会累积梯度\n",
    "        loss.backward()\n",
    "        optimizer.step()\n",
    "        \n",
    "        total_loss += loss.item()\n",
    "        total_correct += get_num_correct(preds, labels)\n",
    "print(\"epoch:\",epoch,\"loss:\",total_loss,\"total_correct:\",total_correct)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "accuracy: 0.8609\n"
     ]
    }
   ],
   "source": [
    "accuracy = total_correct/len(train_set)\n",
    "print(\"accuracy:\",accuracy)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 每个周期的迭代数 = 数据总数/batchsize（当改变batchsize时，也就是改变了更新权重的次数，也就是朝损失函数最小的防线前进的步数）\n",
    "* accuracy = total_correct/len(train_set)\n",
    "* 梯度：告诉我们应该走哪条路能更快的到达loss最小"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.14 神经网络的混淆矩阵\n",
    "* 创建混淆矩阵的两个条件:一个预测的张量和一个有相应真值或标签的张量"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "60000"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 在3.13训练后网络的基础上进行分析\n",
    "len(train_set)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "60000"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(train_set.targets)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "对整个训练集进行预测"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_all_preds(model,loader):\n",
    "    all_preds = torch.tensor([])\n",
    "    for batch in loader:\n",
    "        images,labels = batch\n",
    "        preds = model(images)\n",
    "        all_preds = torch.cat((all_preds,preds), dim=0)\n",
    "    return all_preds"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "prediction_loader = torch.utils.data.DataLoader(train_set, batch_size=10000)\n",
    "train_preds = get_all_preds(network, prediction_loader)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.Size([60000, 10])"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_preds.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n"
     ]
    }
   ],
   "source": [
    "print(train_preds.requires_grad)   #查看训练预测张量的梯度属性"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_preds.grad\n",
    "# 即使训练中关于梯度张量的跟踪已打开，但在没有进行反向传播的情况下依旧不会有梯度的值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<CatBackward at 0x1d964546ba8>"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_preds.grad_fn   # 由于train_preds是经过函数产生的，故具有该属性"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 局部关闭梯度跟踪以减小内存损耗,也可使用torch.set.grad.enabled(False)进行全局关闭\n",
    "with torch.no_grad():\n",
    "    prediction_loader = torch.utils.data.DataLoader(train_set, batch_size=1000)\n",
    "    train_preds = get_all_preds(network, prediction_loader)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "60000"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(train_preds)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n"
     ]
    }
   ],
   "source": [
    "print(train_preds.requires_grad)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_preds.grad"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_preds.grad_fn"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "total_correct: 51988\n",
      "accuracy: 0.8664666666666667\n"
     ]
    }
   ],
   "source": [
    "preds_correct = get_num_correct(train_preds, train_set.targets)\n",
    "print(\"total_correct:\",preds_correct)\n",
    "print(\"accuracy:\",preds_correct/len(train_set))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "绘制混淆矩阵(方法1：)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([9, 0, 0,  ..., 3, 0, 5])\n",
      "torch.Size([60000])\n"
     ]
    }
   ],
   "source": [
    "print(train_set.targets)\n",
    "print(train_set.targets.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([9, 0, 0,  ..., 3, 0, 5])\n",
      "torch.Size([60000])\n"
     ]
    }
   ],
   "source": [
    "print(train_preds.argmax(dim=1))\n",
    "print(train_preds.argmax(dim=1).shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[9, 9],\n",
       "        [0, 0],\n",
       "        [0, 0],\n",
       "        ...,\n",
       "        [3, 3],\n",
       "        [0, 0],\n",
       "        [5, 5]])"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "stack = torch.stack((train_set.targets, train_preds.argmax(dim=1)),dim=1)\n",
    "stack"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[9, 9]"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 使用tolist方法可访问【target，pred】对\n",
    "stack[0].tolist()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建一个混淆矩阵(初始)\n",
    "cmt = torch.zeros(10,10,dtype=torch.int32)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 遍历所有的对，并计算每个组合发生的次数\n",
    "for p in stack:\n",
    "    tl,pl = p.tolist()\n",
    "    cmt[tl,pl] = cmt[tl,pl] + 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[5661,    5,   77,   73,    8,    2,  117,    1,   56,    0],\n",
       "        [  64, 5774,    5,  128,    5,    1,   20,    0,    3,    0],\n",
       "        [ 111,    1, 4692,   82,  768,    1,  299,    0,   46,    0],\n",
       "        [ 546,   20,   20, 5216,  138,    0,   56,    0,    4,    0],\n",
       "        [  21,    6,  364,  297, 4830,    0,  419,    5,   58,    0],\n",
       "        [  27,    6,    8,    1,    0, 5665,    2,  213,    8,   70],\n",
       "        [1871,    9,  612,  127,  498,    0, 2792,    0,   91,    0],\n",
       "        [   0,    0,    0,    0,    0,   49,    0, 5846,    3,  102],\n",
       "        [  40,    1,   23,   20,   13,   15,   25,   15, 5846,    2],\n",
       "        [   1,    0,    1,    0,    0,   20,    0,  307,    5, 5666]], dtype=torch.int32)"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cmt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Confusion matrix, without normalization\n",
      "[[5661    5   77   73    8    2  117    1   56    0]\n",
      " [  64 5774    5  128    5    1   20    0    3    0]\n",
      " [ 111    1 4692   82  768    1  299    0   46    0]\n",
      " [ 546   20   20 5216  138    0   56    0    4    0]\n",
      " [  21    6  364  297 4830    0  419    5   58    0]\n",
      " [  27    6    8    1    0 5665    2  213    8   70]\n",
      " [1871    9  612  127  498    0 2792    0   91    0]\n",
      " [   0    0    0    0    0   49    0 5846    3  102]\n",
      " [  40    1   23   20   13   15   25   15 5846    2]\n",
      " [   1    0    1    0    0   20    0  307    5 5666]]\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAroAAALICAYAAACQF1PTAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjAsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+17YcXAAAgAElEQVR4nOzdd3hU1dbH8e9KQpCqIERSQHoLJXQQRKQriKhIEREExXavvRcsV9Rrb1z7VV9BQWw0adIMvQgKogIKCgGBICgEMCTs94+ZxACBFBNO5tzf53nmYWbPmTPrzCEzK2vW3jHnHCIiIiIifhPmdQAiIiIiIoVBia6IiIiI+JISXRERERHxJSW6IiIiIuJLSnRFRERExJcivA5ARERERPImvOyZzqUd8DoM3IGd051z3b2O43iU6IqIiIiEGJd2gOJ1+nodBgdXjargdQwnotYFEREREfElJboiIiIi4ktqXRAREREJOQamemVO9AqJiIiIiC+poisiIiISagww8zqKIk8VXRERERHxJSW6IiIiIuJLal0QERERCUWajJYjvUIiIiIi4ktKdEVERETEl9S6ICIiIhKKtOpCjlTRFRERERFfUkVXREREJOToL6Plhl4hEREREfElJboiIiIi4ktqXRAREREJRZqMliNVdEVERETEl5ToioiIiIgvqXVBREREJNQYWnUhF/QKiYiIiIgvKdEVEREREV9S64KIiIhIyDGtupALquiKiIiIiC+poisiIiISijQZLUd6hURERETEl5ToioiIiIgvqXVBREREJBRpMlqOVNEVEREREV9SoisiIiIivqTWBREREZGQY1p1IRf0ComIiIiIL6miKyIiIhJqDE1GywVVdEVERETEl5ToioiIiIgvqXVBREREJBRpMlqO9AqJiIiIiC8p0RURERERX1LrgoiIiEjI0Tq6uaFXSERERER8SRVdERERkVAUpnV0c6KKroiIiIj4khJdEREREfEltS6IiIiIhBpDk9FyQa+QiIiIiPiSEl0RERER8SW1LoiIiIiEItOqCzlRRVdEREREfEmJroiIiIj4kloXREREREKO/gRwbugVEhERERFfUkVXREREJBRpMlqOVNEVEREREV9SoisiIiIivqTWBREREZFQpMloOdIrJCIiIiK+pERXRERERHxJrQsiIiIi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\n",
      "text/plain": [
       "<Figure size 720x720 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "from resources.plotcm import plot_confusion_matrix\n",
    "names = (\n",
    "    'T-shirt/top',\n",
    "    'Trouser',\n",
    "    'Pullover',\n",
    "    'Dress',\n",
    "    'Coat',\n",
    "    'Sandal',\n",
    "    'Shirt',\n",
    "    'Sneaker',\n",
    "    'Bag',\n",
    "    'Ankle boot')\n",
    "plt.figure(figsize=(10,10))\n",
    "plot_confusion_matrix(cm, names)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "绘制混淆矩阵(方法2：)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[5661,    5,   77,   73,    8,    2,  117,    1,   56,    0],\n",
       "       [  64, 5774,    5,  128,    5,    1,   20,    0,    3,    0],\n",
       "       [ 111,    1, 4692,   82,  768,    1,  299,    0,   46,    0],\n",
       "       [ 546,   20,   20, 5216,  138,    0,   56,    0,    4,    0],\n",
       "       [  21,    6,  364,  297, 4830,    0,  419,    5,   58,    0],\n",
       "       [  27,    6,    8,    1,    0, 5665,    2,  213,    8,   70],\n",
       "       [1871,    9,  612,  127,  498,    0, 2792,    0,   91,    0],\n",
       "       [   0,    0,    0,    0,    0,   49,    0, 5846,    3,  102],\n",
       "       [  40,    1,   23,   20,   13,   15,   25,   15, 5846,    2],\n",
       "       [   1,    0,    1,    0,    0,   20,    0,  307,    5, 5666]],\n",
       "      dtype=int64)"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "from sklearn.metrics import confusion_matrix\n",
    "from resources.plotcm import plot_confusion_matrix  # plotcm.py文件位于当前文件resources中\n",
    "\n",
    "cm = confusion_matrix(train_set.targets, train_preds.argmax(dim=1))\n",
    "cm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Confusion matrix, without normalization\n",
      "[[5661    5   77   73    8    2  117    1   56    0]\n",
      " [  64 5774    5  128    5    1   20    0    3    0]\n",
      " [ 111    1 4692   82  768    1  299    0   46    0]\n",
      " [ 546   20   20 5216  138    0   56    0    4    0]\n",
      " [  21    6  364  297 4830    0  419    5   58    0]\n",
      " [  27    6    8    1    0 5665    2  213    8   70]\n",
      " [1871    9  612  127  498    0 2792    0   91    0]\n",
      " [   0    0    0    0    0   49    0 5846    3  102]\n",
      " [  40    1   23   20   13   15   25   15 5846    2]\n",
      " [   1    0    1    0    0   20    0  307    5 5666]]\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAroAAALICAYAAACQF1PTAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjAsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+17YcXAAAgAElEQVR4nOzdd3hU1dbH8e9KQpCqIERSQHoLJXQQRKQriKhIEREExXavvRcsV9Rrb1z7VV9BQWw0adIMvQgKogIKCgGBICgEMCTs94+ZxACBFBNO5tzf53nmYWbPmTPrzCEzK2vW3jHnHCIiIiIifhPmdQAiIiIiIoVBia6IiIiI+JISXRERERHxJSW6IiIiIuJLSnRFRERExJcivA5ARERERPImvOyZzqUd8DoM3IGd051z3b2O43iU6IqIiIiEGJd2gOJ1+nodBgdXjargdQwnotYFEREREfElJboiIiIi4ktqXRAREREJOQamemVO9AqJiIiIiC+poisiIiISagww8zqKIk8VXRERERHxJSW6IiIiIuJLal0QERERCUWajJYjvUIiIiIi4ktKdEVERETEl9S6ICIiIhKKtOpCjlTRFRERERFfUkVXREREJOToL6Plhl4hEREREfElJboiIiIi4ktqXRAREREJRZqMliNVdEVERETEl5ToioiIiIgvqXVBREREJNQYWnUhF/QKiYiIiIgvKdEVEREREV9S64KIiIhIyDGtupALquiKiIiIiC+poisiIiISijQZLUd6hURERETEl5ToioiIiIgvqXVBREREJBRpMlqOVNEVEREREV9SoisiIiIivqTWBREREZGQY1p1IRf0ComIiIiIL6miKyIiIhJqDE1GywVVdEVERETEl5ToioiIiIgvqXVBREREJBRpMlqO9AqJiIiIiC8p0RURERERX1LrgoiIiEjI0Tq6uaFXSERERER8SRVdERERkVAUpnV0c6KKroiIiIj4khJdEREREfEltS6IiIiIhBpDk9FyQa+QiIiIiPiSEl0RERER8SW1LoiIiIiEItOqCzlRRVdEREREfEmJroiIiIj4kloXREREREKO/gRwbugVEhERERFfUkVXREREJBRpMlqOVNEVEREREV9SoisiIiIivqTWBREREZFQpMloOdIrJCIiIiK+pERXRERERHxJrQsiIiIi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\n",
      "text/plain": [
       "<Figure size 720x720 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "names = (\n",
    "    'T-shirt/top',\n",
    "    'Trouser',\n",
    "    'Pullover',\n",
    "    'Dress',\n",
    "    'Coat',\n",
    "    'Sandal',\n",
    "    'Shirt',\n",
    "    'Sneaker',\n",
    "    'Bag',\n",
    "    'Ankle boot')\n",
    "plt.figure(figsize=(10,10))\n",
    "plot_confusion_matrix(cm, names)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.15 concatenating和stacking的区分\n",
    "* concatenating是在一个现有的轴上连接一系列的张量\n",
    "* stacking是在一个新的轴上连接一系列的张量(即，我们在所有的张量中创建一个新轴)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 126,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[1, 1, 1]])\n",
      "torch.Size([1, 3])\n",
      "tensor([[1],\n",
      "        [1],\n",
      "        [1]])\n",
      "torch.Size([3, 1])\n"
     ]
    }
   ],
   "source": [
    "# 给张量创建新轴\n",
    "import torch\n",
    "t = torch.tensor([1,1,1]) \n",
    "print(t.unsqueeze(dim=0))\n",
    "print(t.unsqueeze(dim=0).shape)\n",
    "print(t.unsqueeze(dim=1))\n",
    "print(t.unsqueeze(dim=1).shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 132,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([1, 1, 1, 2, 2, 2, 3, 3, 3])\n",
      "tensor([[1, 1, 1],\n",
      "        [2, 2, 2],\n",
      "        [3, 3, 3]])\n",
      "tensor([[1, 1, 1],\n",
      "        [2, 2, 2],\n",
      "        [3, 3, 3]])\n"
     ]
    }
   ],
   "source": [
    "# 使用Pytorch实现concatenating和stacking\n",
    "t1 = torch.tensor([1,1,1])\n",
    "t2 = torch.tensor([2,2,2])\n",
    "t3 = torch.tensor([3,3,3])\n",
    "# Concatenating\n",
    "t_cat = torch.cat((t1,t2,t3), dim=0)\n",
    "print(t_cat)\n",
    "\n",
    "# Stacking\n",
    "t_stack = torch.stack((t1, t2, t3), dim=0)\n",
    "print(t_stack)\n",
    "\n",
    "# Staking相当于先给张量添加一个新轴然后在concat\n",
    "t_stack1 = torch.cat((t1.unsqueeze(0),t2.unsqueeze(0),t3.unsqueeze(0)), dim =0)\n",
    "print(t_stack1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 131,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\wanyu\\Anaconda3\\lib\\site-packages\\h5py\\__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.\n",
      "  from ._conv import register_converters as _register_converters\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Tensor(\"concat:0\", shape=(9,), dtype=int64)\n",
      "Tensor(\"concat_1:0\", shape=(9,), dtype=int64)\n"
     ]
    }
   ],
   "source": [
    "# 使用Tensorflow实现concatenating和stacking\n",
    "import tensorflow as tf\n",
    "# Concatenating\n",
    "t_cat = tf.concat((t1, t2, t3), axis =0)\n",
    "print(t_cat)\n",
    "\n",
    "#Stacking\n",
    "t_stack = tf.concat((t1, t2, t3), axis =0)\n",
    "print(t_stack)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 133,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1 1 1 2 2 2 3 3 3]\n",
      "[[1 1 1]\n",
      " [2 2 2]\n",
      " [3 3 3]]\n"
     ]
    }
   ],
   "source": [
    "# 使用Numpy实现concatenating和stacking\n",
    "import numpy as np\n",
    "t1 = np.array([1,1,1])\n",
    "t2 = np.array([2,2,2])\n",
    "t3 = np.array([3,3,3])\n",
    "# Concatenating\n",
    "t_cat = np.concatenate((t1,t2,t3), axis=0)\n",
    "print(t_cat)\n",
    "# Stacking\n",
    "t_stack = np.stack((t1,t2,t3), axis =0)\n",
    "print(t_stack)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
